#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>

#define IMAGE_MAX_WIDTH 1500
#define IMAGE_MAX_HEIGHT 600
#define RATIO_MAX_HEIGHT 0.8
#define RATIO_MAX_WIDTH  1.0
#define WINDOW_MAIN "main"

using namespace std;
using namespace cv;

vector<float> vKeys;
vector<float> vValues;
float keyMax = -10086;
float keyMin = -10086;
float valueMax = -10086;
float valueMin = -10086;
float singleW = -10086;

float getMax(vector<float> &vect) {
	float fMax = vect[0];
	for(size_t i = 0; i < vect.size(); i ++ ) {
		fMax = (fMax < vect[i]) ? vect[i] : fMax;
	}
	//cout << __func__ << ": Max Value = " << fMax << endl;
	return fMax;
}

float getMin(vector<float> &vect) {
	float fMin = vect[0];
	for(size_t i = 0; i < vect.size(); i ++ ) {
		fMin = (fMin > vect[i]) ? vect[i] : fMin;
	}
	//cout << __func__ << ": Min Value = " << fMin << endl;
	return fMin;
}

void onMouse(int event, int x, int y, int flags, void* img) {
	CvFont font;
    cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1.0f,1.0f);
	float key, value;
	char text[512];
	switch(event) {
	case CV_EVENT_MOUSEMOVE: {
		if( x > 0 && x < cvRound(IMAGE_MAX_WIDTH * RATIO_MAX_WIDTH)) {
			for(size_t i = 0; i < vKeys.size(); i ++ ) {
				int pStart = cvRound((vKeys[i] - keyMin) * singleW);
				//cout << x << ", " << pStart << ", "  << x-pStart << ", " << singleW<< endl;
				if(x >= pStart && (x - pStart) < singleW) {
					key = vKeys[i];
					value = vValues[i];
					sprintf(text, "[ %f ] = [ %f ]", key, value);
					cvRectangle(img, cvPoint(0,0), cvPoint(IMAGE_MAX_WIDTH, cvRound(IMAGE_MAX_HEIGHT * (1-RATIO_MAX_HEIGHT))), cvScalar(0), - 1);
					cvPutText(img, text, cvPoint(0, 30), &font, cvScalar(255,0,0));
					cvShowImage(WINDOW_MAIN, img);
					break;
				}
			}

		} else {
			//out  of bound
		}
	
		break;
	}
	}
}

IplImage *drawDistrubution(vector<float> &v_keys, vector<float> &v_values) {
	cout << "imgSize(" << IMAGE_MAX_WIDTH << "*" << IMAGE_MAX_HEIGHT << "), singleW=" << singleW << endl;
	

	IplImage *outImg = cvCreateImage(cvSize(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT), IPL_DEPTH_8U, 3);
	for(size_t i = 0; i < v_keys.size(); i ++) {
		Point p0, p1;
		p0.x = cvRound((v_keys[i] - keyMin) * singleW);
		p0.y = cvRound(IMAGE_MAX_HEIGHT -  (v_values[i] - valueMin) / (valueMax - valueMin) * IMAGE_MAX_HEIGHT * RATIO_MAX_HEIGHT);

		p1.x = cvRound(p0.x + singleW);
		p1.y = cvRound(IMAGE_MAX_HEIGHT);
		//cout << "p0=" << p0.x << ", " << p0.y << "\t p1=" << p1.x << ", " << p1.y << endl;
		cvRectangle(outImg, p0, p1, cvScalar(0,255,0), -1/*fill*/);
	}

	return outImg;
}

int main(int argc, char **argv) {

	assert(argc == 2);

	vKeys.clear();
	vValues.clear();

	string sline;
	ifstream ifs(argv[1]);
	while (getline(ifs, sline))  {
		stringstream ss(sline);
		float key, value;
		ss >> key >>  value;
		cout << "readed:" << key << " && " << value << endl;
		vKeys.push_back(key);
		vValues.push_back(value);
	}
	ifs.close();
	cvNamedWindow(WINDOW_MAIN);

	keyMax = getMax(vKeys);
	keyMin = getMin(vKeys);
	valueMax = getMax(vValues);
	valueMin = getMin(vValues);
	singleW = (float)IMAGE_MAX_WIDTH * RATIO_MAX_WIDTH / (keyMax - keyMin + 1);

	IplImage *drawedImg = drawDistrubution(vKeys, vValues);
	
	setMouseCallback(WINDOW_MAIN, onMouse, drawedImg);     
	cvShowImage(WINDOW_MAIN, drawedImg);

	cvWaitKey(0);
	return 0;
}
